home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 December / MACPOWER-1997-12.ISO.7z / MACPOWER-1997-12.ISO / AMUG / PROGRAMMING / Raven 1.2 Examples.sit / Raven 1.2 Examples / BoxPaint / Source / Pane.cpp < prev    next >
Text File  |  1997-09-04  |  19KB  |  753 lines

  1. /*
  2.  *  File:       Pane.h
  3.  *  Summary:       A pane displaying the 3D object and a 3D cursor.
  4.  *  Written by: Jesse Jones
  5.  *
  6.  *  Copyright ゥ 1997 Jesse Jones. 
  7.  *    For conditions of distribution and use, see copyright notice in ZTypes.h  
  8.  *
  9.  *  Change History (most recent first):    
  10.  *
  11.  *         <2>     5/02/97    JDJ        OnTrackStop now only has a stopPt argument.
  12.  *         <1>     2/07/97    JDJ        Created
  13.  */
  14.  
  15. #include "Pane.h"
  16.  
  17. #include <QD3DAcceleration.h>
  18. #include <QD3DMath.h>
  19.  
  20. #include <Z3DCameras.h>
  21. #include <Z3DDrawContexts.h>
  22. #include <Z3DGroups.h>
  23. #include <Z3DLights.h>
  24. #include <Z3DPicks.h>
  25. #include <Z3DRenderingLoops.h>
  26. #include <Z3DRenderers.h>
  27. #include <Z3DTransforms.h>
  28. #include <Z3DUtils.h>
  29. #include <ZCursor.h>
  30. #include <ZTracker.h>
  31. #include <ZView.h>
  32. #include <ZWindow.h>
  33.  
  34. #include "Doc.h"
  35.  
  36.  
  37. //-----------------------------------
  38. //    Constants
  39. //
  40. const MenuCommand kSoftwareRendererCmd = "Software Renderer";
  41. const MenuCommand kHardwareRendererCmd = "Hardware Renderer";
  42. const MenuCommand kBestRendererCmd     = "Best Renderer";
  43.  
  44.  
  45. // ===================================================================================
  46. //    Internal Functions
  47. // ===================================================================================
  48.  
  49. //---------------------------------------------------------------
  50. //
  51. // GetUpVector
  52. //
  53. // Returns a default vector that points as much toward the y axis 
  54. // as it can. Expects the vectors to be normalized. At this point, 
  55. // what to do if the forward vector lies on the y axis is a point 
  56. // of thought. Currently, it returns vector pointing down the -Z 
  57. // axis.
  58. //
  59. //---------------------------------------------------------------
  60. static T3DVector GetUpVector(const T3DVector& forwardVector)
  61. {
  62.     T3DVector upVector;
  63.     
  64.     if (forwardVector.x == 0.0 && forwardVector.z == 0.0) {
  65.         upVector.x = 0.0; 
  66.         upVector.y = 0.0; 
  67.         upVector.z = -1.0; 
  68.         
  69.     } else {
  70.         T3DVector tempVector(0.0, 1.0, 0.0);
  71.         
  72.         T3DVector orthogonalVector = CrossProduct(tempVector, forwardVector);
  73.         
  74.         tempVector = CrossProduct(forwardVector, orthogonalVector);
  75.         
  76.         upVector = Normalize(tempVector);
  77.     }
  78.     
  79.     return upVector;
  80. }
  81.  
  82. #pragma mark -
  83.  
  84. // ===================================================================================
  85. //    class C3DBusyCursorIdler
  86. // ===================================================================================
  87. class C3DBusyCursorIdler : public T3DViewIdler {
  88.  
  89.     typedef T3DViewIdler Inherited;
  90.  
  91. //-----------------------------------
  92. //    Initialization/Destruction
  93. //
  94. public:
  95.     virtual                ~C3DBusyCursorIdler();
  96.                         
  97.                         C3DBusyCursorIdler();
  98.                         
  99. //-----------------------------------
  100. //    Inherited API
  101. //
  102. protected:    
  103.     virtual bool         OnIdle();
  104. };
  105.  
  106.  
  107. //---------------------------------------------------------------
  108. //
  109. // C3DBusyCursorIdler::~C3DBusyCursorIdler
  110. //
  111. //---------------------------------------------------------------
  112. C3DBusyCursorIdler::~C3DBusyCursorIdler()
  113. {
  114. }
  115.  
  116.  
  117. //---------------------------------------------------------------
  118. //
  119. // C3DBusyCursorIdler::C3DBusyCursorIdler
  120. //
  121. //---------------------------------------------------------------
  122. C3DBusyCursorIdler::C3DBusyCursorIdler()
  123. {
  124. }
  125.  
  126.  
  127. //---------------------------------------------------------------
  128. //
  129. // C3DBusyCursorIdler::OnIdle
  130. //
  131. //---------------------------------------------------------------
  132. bool C3DBusyCursorIdler::OnIdle()
  133. {
  134.     UCursorUtils::ForceBusy();
  135.     
  136.     return true;                    // keep on truckin
  137. }
  138.  
  139. #pragma mark -
  140.     
  141.     
  142. // ===================================================================================
  143. //    class CRotateTracker
  144. // ===================================================================================
  145. class CRotateTracker : public TTracker {
  146.  
  147.     typedef TTracker Inherited;
  148.  
  149. //-----------------------------------
  150. //    Initialization/Destruction
  151. //
  152. public:
  153.     virtual             ~CRotateTracker();
  154.     
  155.                         CRotateTracker(TPane* pane, CDocument* doc, const TPoint& startPt);
  156.     
  157. //-----------------------------------
  158. //    Inherited API
  159. //
  160. protected:
  161.     virtual    void        OnTrackStart(const TPoint& startPt);
  162.         
  163.     virtual    TTracker*     OnTrackContinue(const TPoint& anchorPt, const TPoint& prevPt, const TPoint& nextPt, bool mouseMoved);
  164.     
  165.     virtual    void        OnTrackStop(const TPoint& stopPt);
  166.  
  167. //-----------------------------------
  168. //    Member Data
  169. //
  170. protected:
  171.     CDocument*    mDoc;
  172. };
  173.  
  174.  
  175. //---------------------------------------------------------------
  176. //
  177. // CRotateTracker::~CRotateTracker
  178. //
  179. //---------------------------------------------------------------
  180. CRotateTracker::~CRotateTracker()
  181. {
  182. }
  183.  
  184.  
  185. //---------------------------------------------------------------
  186. //
  187. // CRotateTracker::CRotateTracker
  188. //
  189. //---------------------------------------------------------------
  190. CRotateTracker::CRotateTracker(TPane* pane, CDocument* doc, const TPoint& startPt) : TTracker(pane, startPt, kDontTrackNonMovement)
  191. {
  192.     ASSERT(doc != nil);
  193.     
  194.     mDoc = doc;
  195. }
  196.  
  197.  
  198. //---------------------------------------------------------------
  199. //
  200. // CRotateTracker::OnTrackStart
  201. //
  202. //---------------------------------------------------------------
  203. void CRotateTracker::OnTrackStart(const TPoint& startPt)
  204. {
  205.     #pragma unused(startPt)
  206.     
  207.     HideCursor();
  208. }
  209.  
  210.  
  211. //---------------------------------------------------------------
  212. //
  213. // CRotateTracker::OnTrackContinue
  214. //
  215. //---------------------------------------------------------------
  216. TTracker* CRotateTracker::OnTrackContinue(const TPoint& anchorPt, const TPoint& prevPt, const TPoint& nextPt, bool mouseMoved)
  217. {
  218.     #pragma unused(anchorPt, mouseMoved)
  219.  
  220.     float dx = prevPt.v - nextPt.v;
  221.     float dy = nextPt.h - prevPt.h;
  222.         
  223.     float xRot = dx*kQ3Pi/mPane->GetWidth();
  224.     float yRot = dy*kQ3Pi/mPane->GetHeight();
  225.  
  226.     if (xRot != 0.0 || yRot != 0.0) {
  227.         T3DMatrix tempMatrix;
  228.         tempMatrix.SetRotateXYZ(xRot, yRot, 0.0);
  229.         
  230.         mDoc->TransformModel(tempMatrix);
  231.         mPane->HandleUpdate();
  232.     }
  233.     
  234.     return this;
  235. }
  236.  
  237.  
  238. //---------------------------------------------------------------
  239. //
  240. // CRotateTracker::OnTrackStop
  241. //
  242. //---------------------------------------------------------------
  243. void CRotateTracker::OnTrackStop(const TPoint& stopPt)
  244. {
  245.     #pragma unused(stopPt)
  246.  
  247.     ShowCursor();
  248. }
  249.  
  250. #pragma mark -
  251.  
  252. // ===================================================================================
  253. //    class CDrawTracker
  254. // ===================================================================================
  255. class CDrawTracker : public TTracker {
  256.  
  257.     typedef TTracker Inherited;
  258.  
  259. //-----------------------------------
  260. //    Initialization/Destruction
  261. //
  262. public:
  263.     virtual             ~CDrawTracker();
  264.     
  265.                         CDrawTracker(TPane* pane, CDocument* doc, const TPoint& startPt);
  266.     
  267. //-----------------------------------
  268. //    Inherited API
  269. //
  270. protected:
  271.     virtual    void        OnTrackStart(const TPoint& startPt);
  272.         
  273.     virtual    TTracker*     OnTrackContinue(const TPoint& anchorPt, const TPoint& prevPt, const TPoint& nextPt, bool mouseMoved);
  274.     
  275.     virtual    void        OnTrackStop(const TPoint& stopPt);
  276.  
  277. //-----------------------------------
  278. //    Member Data
  279. //
  280. protected:
  281.     CDocument*                mDoc;
  282.     T3DWindowPointPick*        mPickObject;
  283.     TQ3PickDetail            mMask;
  284.     TQ3Param2D                mFrom;
  285.     CPencil&                mCursor;
  286.     T3DView&                mView;
  287.     CTextureMap&            mTexture;
  288.     
  289.     bool                    mFirstTime;
  290.     T3DObjectPtr            mLastHitObject;
  291. };
  292.  
  293.  
  294. //---------------------------------------------------------------
  295. //
  296. // CDrawTracker::~CDrawTracker
  297. //
  298. //---------------------------------------------------------------
  299. CDrawTracker::~CDrawTracker()
  300. {
  301.     delete mPickObject;
  302. }
  303.  
  304.  
  305. //---------------------------------------------------------------
  306. //
  307. // CDrawTracker::CDrawTracker
  308. //
  309. //---------------------------------------------------------------
  310. CDrawTracker::CDrawTracker(TPane* pane, CDocument* doc, const TPoint& startPt) : TTracker(pane, startPt, kDontTrackNonMovement), mView(dynamic_cast<CPane*>(pane)->GetView()), mCursor(dynamic_cast<CPane*>(pane)->GetCursor()), mTexture(dynamic_cast<CPane*>(pane)->GetDoc()->GetTexture())
  311. {
  312.     ASSERT(doc != nil);
  313.     
  314.     mDoc = doc;
  315.  
  316.     mFrom.u = -1.0;
  317.     mFrom.v = -1.0;
  318.             
  319.     mMask = kQ3PickDetailMaskObject | kQ3PickDetailMaskPath | kQ3PickDetailMaskUV |
  320.             kQ3PickDetailMaskXYZ | kQ3PickDetailMaskNormal;
  321.  
  322.     mPickObject = new T3DWindowPointPick(mMask);
  323. }
  324.  
  325.  
  326. //---------------------------------------------------------------
  327. //
  328. // CDrawTracker::OnTrackStart
  329. //
  330. //---------------------------------------------------------------
  331. void CDrawTracker::OnTrackStart(const TPoint& startPt)
  332. {
  333.     #pragma unused(startPt)
  334.     
  335.     HideCursor();
  336.     mCursor.Show();
  337.     
  338.     mFirstTime = true;
  339. }
  340.  
  341.  
  342. //---------------------------------------------------------------
  343. //
  344. // CDrawTracker::OnTrackContinue
  345. //
  346. // This code seems to screw up occasionally (especially near the
  347. // poles). Note that the original SDK app misbehaved in the same
  348. // way...
  349. //
  350. //---------------------------------------------------------------
  351. TTracker* CDrawTracker::OnTrackContinue(const TPoint& anchorPt, const TPoint& prevPt, const TPoint& nextPt, bool mouseMoved)
  352. {
  353.     #pragma unused(anchorPt, prevPt, mouseMoved)
  354.  
  355.     const float kCursorSize = 0.25;            // the size in relation to the model being
  356.  
  357.     // Adjust the pick point
  358.     mPickObject->SetPoint(T2DPoint(nextPt));
  359.     
  360.     ulong numHits = dynamic_cast<CPane*>(mPane)->HandlePick(mPickObject);
  361.     if (numHits > 0 && mPickObject->HasDetail(0, mMask)) {        
  362.         T3DPickEntry entry = mPickObject->GetEntry(0);
  363.  
  364.         // Move the 3D cursor to the new position.
  365.         S3DCursorLocation cursorPlacement;
  366.         cursorPlacement.location = entry.GetXYZPoint();
  367.         cursorPlacement.toward   = -entry.GetNormal();                        // Point it into the picked model for our cursor
  368.         cursorPlacement.up       = GetUpVector(cursorPlacement.toward);    // Since we don't have an up vector, get a default one
  369.  
  370.         mCursor.MoveTo(cursorPlacement);
  371.  
  372.         // We don't want to do this everytime
  373.         T3DObjectPtr object = entry.GetObject();
  374.         if (object != mLastHitObject) {
  375.             mLastHitObject = object;                // Reset it for next time
  376.         
  377.             // Adjust the cursor to match the object's group.
  378.             T3DHitPath hitPath = entry.GetHitPath();                
  379.             T3DGroupPtr leafGroup = hitPath.GetLeafGroup();
  380.             
  381.             if (T3DDisplayGroup* leaf = dynamic_cast<T3DDisplayGroup*>(leafGroup.Get()))
  382.                 mCursor.Scale(*leaf, mView, kCursorSize);
  383.         }
  384.         
  385.         // Paint a line on the texture if the UV coordinate has changed.
  386.         TQ3Param2D to = entry.GetUV();
  387.         if (mFrom.u != to.u || mFrom.v != to.v) {
  388.             if (mFirstTime) {
  389.                 mFrom = to;                            // need a valid from
  390.                 mFirstTime = false;
  391.             }
  392.             
  393.             mTexture.DrawLine(mFrom, to);
  394.             mDoc->SetDirty();
  395.  
  396.             mPane->HandleUpdate();
  397.         }
  398.  
  399.         mPickObject->EmptyHitList();
  400.  
  401.         mFrom = to;
  402.     }
  403.     
  404.     return this;
  405. }
  406.  
  407.  
  408. //---------------------------------------------------------------
  409. //
  410. // CDrawTracker::OnTrackStop
  411. //
  412. //---------------------------------------------------------------
  413. void CDrawTracker::OnTrackStop(const TPoint& stopPt)
  414. {
  415.     #pragma unused(stopPt)
  416.  
  417.     mCursor.Hide();
  418.     ShowCursor();
  419.     
  420.     mPane->Invalidate();            // need to erase cursor
  421. }
  422.  
  423. #pragma mark -
  424.  
  425. // ===================================================================================
  426. //    class CPane
  427. // ===================================================================================
  428.  
  429. static TReanimatorRegister<CPane> sMyPaneRegistrar;
  430.  
  431. //---------------------------------------------------------------
  432. //
  433. // CPane::~CPane
  434. //
  435. //---------------------------------------------------------------
  436. CPane::~CPane()
  437. {
  438. }
  439.  
  440.  
  441. //---------------------------------------------------------------
  442. //
  443. // CPane::CPane
  444. //
  445. //---------------------------------------------------------------
  446. CPane::CPane(TView* superView) : TPane(superView), MCommander(nil)
  447. {
  448.     mDoc = nil;
  449. }
  450.  
  451.  
  452. //---------------------------------------------------------------
  453. //
  454. // CPane::Create                                        [static]
  455. //
  456. //---------------------------------------------------------------
  457. MReanimatable* CPane::Create(MReanimatable* parent)
  458. {
  459.     return new CPane(dynamic_cast<TView*>(parent));
  460. }
  461.  
  462. #pragma mark ハ
  463.  
  464. //---------------------------------------------------------------
  465. //
  466. // CPane::OnReanimated
  467. //
  468. //---------------------------------------------------------------
  469. void CPane::OnReanimated()
  470. {
  471.     Inherited::OnReanimated();
  472.  
  473.     TWindow* window = dynamic_cast<TWindow*>(this->GetTopView());
  474.     ASSERT(window != nil);
  475.     
  476.     mDoc = dynamic_cast<CDocument*>(window->GetSuperCommander());
  477.     ASSERT(mDoc != nil);
  478.     
  479.     this->CreateView();
  480. }
  481.  
  482.  
  483. //---------------------------------------------------------------
  484. //
  485. // CPane::OnDraw
  486. //
  487. //---------------------------------------------------------------
  488. void CPane::OnDraw(TCanvas& canvas, const TRegion& dirtyRgn)
  489. {
  490.     #pragma unused(dirtyRgn)
  491.         
  492.     TUseCanvasPort usePort(canvas);
  493.     
  494.     T3DRenderLoop loop(mView);
  495.     do {
  496.         this->SubmitScene();
  497.     } while (loop.Rendering());
  498. }
  499.  
  500.  
  501. //---------------------------------------------------------------
  502. //
  503. // CPane::HandlePick
  504. //
  505. //---------------------------------------------------------------
  506. ulong CPane::HandlePick(T3DPick* pickObject)
  507. {
  508.     ulong hits = 0;
  509.     
  510.     T3DPickLoop loop(mView, pickObject);
  511.     do {
  512.         this->SubmitScene();
  513.     } while (loop.Rendering());
  514.     
  515.     hits = pickObject->GetNumHits();
  516.     
  517.     return hits;
  518. }
  519.  
  520.  
  521. //---------------------------------------------------------------
  522. //
  523. // CPane::OnMouseDown
  524. //
  525. //---------------------------------------------------------------
  526. bool CPane::OnMouseDown(const TMouseEvent& event)
  527. {
  528.     TTracker* tracker = nil;
  529.     
  530.     if (event.WasOptionKeyDown()) {
  531.         tracker = new CRotateTracker(this, mDoc, event.GetPosition());
  532.         tracker->Post();
  533.     
  534.     } else {
  535.         tracker = new CDrawTracker(this, mDoc, event.GetPosition());
  536.         tracker->Post();
  537.     }
  538.         
  539.     return kHandled;
  540. }
  541.  
  542.  
  543. //---------------------------------------------------------------
  544. //
  545. // CPane::OnAdjustCursor
  546. //
  547. //---------------------------------------------------------------
  548. bool CPane::OnAdjustCursor(const TEvent& event)
  549. {    
  550.     if (event.WasOptionKeyDown())
  551.         UCursorUtils::SetCursor(kOpenHandCursor);
  552.     else
  553.         UCursorUtils::SetCursor(kArrowCursor);
  554.         
  555.     return kHandled;
  556. }
  557.  
  558.  
  559. //---------------------------------------------------------------
  560. //
  561. // CPane::OnKeyDown
  562. //
  563. //---------------------------------------------------------------
  564. bool CPane::OnKeyDown(const TKeyEvent& event)
  565. {
  566.     bool handled = true;
  567.     
  568.     const float kRotateBy = 0.05;            // rotate by 5%
  569.     
  570.     float dx = 0.0;
  571.     float dy = 0.0;
  572.     
  573.     char ch = event.GetChar();
  574.         
  575.     switch (ch) {
  576.         case kLeftArrowChar:
  577.             dy = -kRotateBy;
  578.             break;
  579.             
  580.         case kRightArrowChar:
  581.             dy = kRotateBy;
  582.             break;
  583.             
  584.         case kUpArrowChar:
  585.             dx = -kRotateBy;
  586.             break;
  587.             
  588.         case kDownArrowChar:
  589.             dx = kRotateBy;
  590.             break;
  591.             
  592.         default:
  593.             handled = false;
  594.     }
  595.         
  596.     if (dx != 0.0 || dy != 0.0) {
  597.         T3DMatrix tempMatrix;
  598.         tempMatrix.SetRotateXYZ(dx*kQ32Pi, dy*kQ32Pi, 0.0);
  599.         
  600.         mDoc->TransformModel(tempMatrix);
  601.         this->HandleUpdate();                // for auto-repeat
  602.     }
  603.     
  604.     return handled;
  605. }
  606.  
  607.  
  608. //---------------------------------------------------------------
  609. //
  610. // CPane::OnMenuCommand
  611. //
  612. //---------------------------------------------------------------
  613. bool CPane::OnMenuCommand(const MenuCommand& command)
  614. {
  615.     bool handled = false;
  616.     
  617.     T3DRendererPtr rendererPtr = mView.GetRenderer();
  618.     if (T3DInteractiveRenderer* renderer = dynamic_cast<T3DInteractiveRenderer*>(rendererPtr.Get())) {
  619.         long engineID = renderer->GetEngineID();
  620.         
  621.         handled = true;
  622.  
  623.         if (command == kSoftwareRendererCmd && engineID != kQAEngine_AppleSW) {
  624.             renderer->SetEngineID(kQAEngine_AppleSW);
  625.             mView.SetRenderer(*renderer);                // ・・・ハis this really neccesary?
  626.         
  627.         } else if (command == kHardwareRendererCmd && engineID != kQAEngine_AppleHW) {
  628.             renderer->SetEngineID(kQAEngine_AppleHW);
  629.             mView.SetRenderer(*renderer);
  630.         
  631.         } else if (command == kBestRendererCmd && engineID != kQAVendor_BestChoice) {
  632.             renderer->SetEngineID(kQAVendor_BestChoice);
  633.             mView.SetRenderer(*renderer);
  634.         
  635.         } else
  636.             handled = false;
  637.     }
  638.         
  639.     return handled;
  640. }
  641.  
  642.         
  643. //---------------------------------------------------------------
  644. //
  645. // CPane::OnCommandStatus
  646. //
  647. //---------------------------------------------------------------
  648. bool CPane::OnCommandStatus(const MenuCommand& command, SCommandStatus& status)
  649. {
  650.     bool handled = true;
  651.     
  652.     long engineID = '????';
  653.     
  654.     T3DRendererPtr rendererPtr = mView.GetRenderer();
  655.     if (T3DInteractiveRenderer* renderer = dynamic_cast<T3DInteractiveRenderer*>(rendererPtr.Get()))
  656.         engineID = renderer->GetEngineID();
  657.         
  658.     if (command == kSoftwareRendererCmd) {
  659.         status.enabled = true;
  660.         status.mark    = engineID == kQAEngine_AppleSW ? kCheckMarkChar : noMark;
  661.     
  662.     } else if (command == kHardwareRendererCmd) {
  663.         status.enabled = true;
  664.         status.mark    = engineID == kQAEngine_AppleHW ? kCheckMarkChar : noMark;
  665.     
  666.     } else if (command == kBestRendererCmd) {
  667.         status.enabled = true;
  668.         status.mark    = engineID == kQAVendor_BestChoice ? kCheckMarkChar : noMark;
  669.  
  670.     } else
  671.         handled = false;
  672.         
  673.     return handled;
  674. }
  675.     
  676. #pragma mark ハ
  677.  
  678. //---------------------------------------------------------------
  679. //
  680. // CPane::CreateView
  681. //
  682. //---------------------------------------------------------------
  683. void CPane::CreateView()
  684. {    
  685.     // Create and set draw context.
  686.     SMacDrawContextData drawContextData((CWindowPtr) this->GetGrafPort(), T3DColorARGB(0.0, 0.2, 1.0, 1.0));
  687.     mView.SetDrawContext(T3DMacDrawContext(drawContextData));
  688.     
  689.     // Create and set renderer.
  690.     mView.SetRenderer(T3DInteractiveRenderer());
  691.     
  692.     // Create and set camera.
  693.     TQ3ViewAngleAspectCameraData perspectiveData;
  694.     perspectiveData.cameraData.placement.cameraLocation  = T3DPoint(0.0, 0.0, 3.0);
  695.     perspectiveData.cameraData.placement.pointOfInterest = T3DPoint(0.0, 0.0, 0.0);
  696.     perspectiveData.cameraData.placement.upVector          = T3DVector(0.0, 1.0, 0.0);
  697.     perspectiveData.cameraData.range.hither              = 0.00001;
  698.     perspectiveData.cameraData.range.yon                  = 10;
  699.     perspectiveData.cameraData.viewPort.origin.x         = -1.0;
  700.     perspectiveData.cameraData.viewPort.origin.y         = 1.0;
  701.     perspectiveData.cameraData.viewPort.width            = 2.0;
  702.     perspectiveData.cameraData.viewPort.height           = 2.0;
  703.  
  704.     perspectiveData.fov                = 1.0;
  705.     perspectiveData.aspectRatioXToY    = (float) this->GetWidth()/this->GetHeight();
  706.         
  707.     mView.SetCamera(T3DViewAngleAspectCamera(perspectiveData));
  708.     
  709.     // Create and set lights.    
  710.     T3DLightGroup lights;
  711.     
  712.     lights.AddObject(T3DAmbientLight(kRGBWhite, 0.3));
  713.     lights.AddObject(T3DPointLight(kRGBWhite, 0.6, T3DPoint(-10.0, 0.0, 10.0)));
  714.     lights.AddObject(T3DDirectionalLight(kRGBWhite, 0.2, T3DVector(10.0, 0.0, 10.0)));
  715.  
  716.     mView.SetLightGroup(lights);
  717.  
  718.     // Install an idler so the cursor spins during long operations.
  719.     mView.SetIdleMethod(new C3DBusyCursorIdler);
  720. }
  721.  
  722.  
  723. //---------------------------------------------------------------
  724. //
  725. // CPane::SubmitScene
  726. //
  727. //---------------------------------------------------------------
  728. void CPane::SubmitScene()
  729. {            
  730.     S3DScene scene = mDoc->GetScene();
  731.         
  732.     // Styles
  733.     scene.interpolation->Submit(mView);
  734.     scene.backFacing->Submit(mView);
  735.     scene.fillStyle->Submit(mView);
  736.         
  737.     {
  738.     // Save the current graphic state.
  739.     T3DPushState saveState(mView);
  740.         
  741.         // Rotation
  742.         T3DMatrixTransform::Submit(scene.rotation, mView);
  743.  
  744.         // Model
  745.         scene.model->Submit(mView);
  746.     }
  747.     
  748.     // Cursor
  749.     mCursor.Submit(mView);        
  750. }
  751.  
  752.  
  753.